#include "MyIOCTL.h"

extern const char *PacketNames[];

void MY_IOCTL_EMPTY::DeserializeEmpty(void *pBuffer, long bufSize, unsigned char packType)
{
	buffer.SetBuffer(pBuffer, bufSize);
	packetName = PacketNames[packType];
	buffer.Read(&isCompleted, sizeof(isCompleted));
	if (isCompleted)
	{
		buffer.Read(&status, sizeof(status));
	}
}

void MY_IOCTL_INTERNAL_USB_GET_BUS_INFO::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&TotalBandwidth,       sizeof(TotalBandwidth));
		buffer.Read(&ConsumedBandwidth,    sizeof(ConsumedBandwidth));
		buffer.Read(&ControllerNameLength, sizeof(ControllerNameLength));
	}
}

void MY_IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}
	buffer.Read(&ActualLength, sizeof(ActualLength));

	HubName = std::auto_ptr<wchar_t>(new wchar_t[ActualLength]);
	wchar_t *pHubName = HubName.get();
	for (i=0; i<ActualLength; ++i)
	{
		buffer.Read(&pHubName[i],  sizeof(wchar_t));
	}
}

void MY_IOCTL_INTERNAL_USB_GET_HUB_NAME::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}
	buffer.Read(&ActualLength, sizeof(ActualLength));

	HubName = std::auto_ptr<wchar_t>(new wchar_t[ActualLength]);
	wchar_t *pHubName = HubName.get();
	for (i=0; i<ActualLength; ++i)
	{
		buffer.Read(&pHubName[i],  sizeof(wchar_t));
	}	
}

void MY_IOCTL_INTERNAL_USB_GET_PORT_STATUS::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&portStatusFlags, sizeof(portStatusFlags));
	}
}

void MY_IOCTL_USB_GET_HUB_CAPABILITIES::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&HubIs2xCapable, sizeof(HubIs2xCapable));
	}
}

void MY_IOCTL_USB_GET_HUB_CAPABILITIES_EX::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&hubFlags.ul, sizeof(hubFlags.ul));
	}
}

void MY_IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO::DeserializeUsbIdString(std::auto_ptr<wchar_t> &pStr)
{
	unsigned long LengthInBytes, i, strLength;
	buffer.Read(&LengthInBytes, sizeof(LengthInBytes));
	
	strLength = LengthInBytes/sizeof(wchar_t);
	pStr = std::auto_ptr<wchar_t>(new wchar_t[strLength]);
	wchar_t *pwStr = pStr.get();
	for (i=0; i<strLength; ++i)
	{
		buffer.Read(&pwStr[i], sizeof(wchar_t));
	}
}

void MY_IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO::DeserializeGUID(MY_GUID &guid)
{
	buffer.Read(&guid.Data1, sizeof(guid.Data1));
	buffer.Read(&guid.Data2, sizeof(guid.Data2));
	buffer.Read(&guid.Data3, sizeof(guid.Data3));
	buffer.Read( guid.Data4, sizeof(guid.Data4));
}

void MY_IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}

	buffer.Read(&Version,     sizeof(Version));
	buffer.Read(&Length,      sizeof(Length));
	buffer.Read(&HubFlags.ul, sizeof(HubFlags.ul));

	DeserializeUsbIdString(HardwareIds);
	DeserializeUsbIdString(CompatibleIds);
	DeserializeUsbIdString(DeviceDescription);

	buffer.Read(&UxdSettings.Version, sizeof(UxdSettings.Version));

	DeserializeGUID(UxdSettings.PnpGuid);
	DeserializeGUID(UxdSettings.OwnerGuid);

	buffer.Read(&UxdSettings.DeleteOnShutdown,   sizeof(UxdSettings.DeleteOnShutdown));
	buffer.Read(&UxdSettings.DeleteOnReload,     sizeof(UxdSettings.DeleteOnReload));
	buffer.Read(&UxdSettings.DeleteOnDisconnect, sizeof(UxdSettings.DeleteOnDisconnect));
}

void MY_IOCTL_INTERNAL_USB_GET_TOPOLOGY_ADDRESS::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}
	buffer.Read(&PciBusNumber,      sizeof(PciBusNumber));
	buffer.Read(&PciDeviceNumber,   sizeof(PciDeviceNumber));
	buffer.Read(&PciFunctionNumber, sizeof(PciFunctionNumber));
	buffer.Read(&RootHubPortNumber, sizeof(RootHubPortNumber));
	buffer.Read( HubPortNumber,     sizeof(HubPortNumber));
}

void MY_IOCTL_USB_GET_NODE_CONNECTION_INFORMATION::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	buffer.Read(&ConnectionIndex, sizeof(ConnectionIndex));
	if (!isCompleted)
	{				
		return;
	}	

	buffer.Read(&DeviceDescriptor.bLength,            sizeof(DeviceDescriptor.bLength));
	buffer.Read(&DeviceDescriptor.bDescriptorType,    sizeof(DeviceDescriptor.bDescriptorType));
	buffer.Read(&DeviceDescriptor.bcdUSB,             sizeof(DeviceDescriptor.bcdUSB));
	buffer.Read(&DeviceDescriptor.bDeviceClass,       sizeof(DeviceDescriptor.bDeviceClass));
	buffer.Read(&DeviceDescriptor.bDeviceSubClass,    sizeof(DeviceDescriptor.bDeviceSubClass));
	buffer.Read(&DeviceDescriptor.bDeviceProtocol,    sizeof(DeviceDescriptor.bDeviceProtocol));
	buffer.Read(&DeviceDescriptor.bMaxPacketSize0,    sizeof(DeviceDescriptor.bMaxPacketSize0));
	buffer.Read(&DeviceDescriptor.idVendor,           sizeof(DeviceDescriptor.idVendor));
	buffer.Read(&DeviceDescriptor.idProduct,          sizeof(DeviceDescriptor.idProduct));
	buffer.Read(&DeviceDescriptor.bcdDevice,          sizeof(DeviceDescriptor.bcdDevice));
	buffer.Read(&DeviceDescriptor.iManufacturer,      sizeof(DeviceDescriptor.iManufacturer));
	buffer.Read(&DeviceDescriptor.iProduct,           sizeof(DeviceDescriptor.iProduct));
	buffer.Read(&DeviceDescriptor.iSerialNumber,      sizeof(DeviceDescriptor.iSerialNumber));
	buffer.Read(&DeviceDescriptor.bNumConfigurations, sizeof(DeviceDescriptor.bNumConfigurations));

	buffer.Read(&CurrentConfigurationValue, sizeof(CurrentConfigurationValue));
	buffer.Read(&LowSpeed,                  sizeof(LowSpeed));
	buffer.Read(&DeviceIsHub,               sizeof(DeviceIsHub));
	buffer.Read(&DeviceAddress,             sizeof(DeviceAddress));
	buffer.Read(&NumberOfOpenPipes,         sizeof(NumberOfOpenPipes));
	buffer.Read(&ConnectionStatus,          sizeof(ConnectionStatus));

	PipeList = std::auto_ptr<MY_USB_PIPE_INFO>(new MY_USB_PIPE_INFO[NumberOfOpenPipes]);
	MY_USB_PIPE_INFO *pPipeList = PipeList.get();
	for (i=0; i<NumberOfOpenPipes; ++i)
	{
		MY_USB_ENDPOINT_DESCRIPTOR *pED = (MY_USB_ENDPOINT_DESCRIPTOR *) &pPipeList[i].EndpointDescriptor;
		buffer.Read(&pED->bLength,          sizeof(pED->bLength));
		buffer.Read(&pED->bDescriptorType,  sizeof(pED->bDescriptorType));
		buffer.Read(&pED->bEndpointAddress, sizeof(pED->bEndpointAddress));
		buffer.Read(&pED->bmAttributes,     sizeof(pED->bmAttributes));
		buffer.Read(&pED->wMaxPacketSize,   sizeof(pED->wMaxPacketSize));
		buffer.Read(&pED->bInterval,        sizeof(pED->bInterval));

		buffer.Read(&pPipeList[i].ScheduleOffset, sizeof(pPipeList[i].ScheduleOffset));
	}
}

// This function is identical to the previous one except one line
// TODO: fix this
void MY_IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	buffer.Read(&ConnectionIndex, sizeof(ConnectionIndex));
	if (!isCompleted)
	{				
		return;
	}	

	buffer.Read(&DeviceDescriptor.bLength,            sizeof(DeviceDescriptor.bLength));
	buffer.Read(&DeviceDescriptor.bDescriptorType,    sizeof(DeviceDescriptor.bDescriptorType));
	buffer.Read(&DeviceDescriptor.bcdUSB,             sizeof(DeviceDescriptor.bcdUSB));
	buffer.Read(&DeviceDescriptor.bDeviceClass,       sizeof(DeviceDescriptor.bDeviceClass));
	buffer.Read(&DeviceDescriptor.bDeviceSubClass,    sizeof(DeviceDescriptor.bDeviceSubClass));
	buffer.Read(&DeviceDescriptor.bDeviceProtocol,    sizeof(DeviceDescriptor.bDeviceProtocol));
	buffer.Read(&DeviceDescriptor.bMaxPacketSize0,    sizeof(DeviceDescriptor.bMaxPacketSize0));
	buffer.Read(&DeviceDescriptor.idVendor,           sizeof(DeviceDescriptor.idVendor));
	buffer.Read(&DeviceDescriptor.idProduct,          sizeof(DeviceDescriptor.idProduct));
	buffer.Read(&DeviceDescriptor.bcdDevice,          sizeof(DeviceDescriptor.bcdDevice));
	buffer.Read(&DeviceDescriptor.iManufacturer,      sizeof(DeviceDescriptor.iManufacturer));
	buffer.Read(&DeviceDescriptor.iProduct,           sizeof(DeviceDescriptor.iProduct));
	buffer.Read(&DeviceDescriptor.iSerialNumber,      sizeof(DeviceDescriptor.iSerialNumber));
	buffer.Read(&DeviceDescriptor.bNumConfigurations, sizeof(DeviceDescriptor.bNumConfigurations));

	buffer.Read(&CurrentConfigurationValue, sizeof(CurrentConfigurationValue));
	buffer.Read(&Speed,                     sizeof(Speed));
	buffer.Read(&DeviceIsHub,               sizeof(DeviceIsHub));
	buffer.Read(&DeviceAddress,             sizeof(DeviceAddress));
	buffer.Read(&NumberOfOpenPipes,         sizeof(NumberOfOpenPipes));
	buffer.Read(&ConnectionStatus,          sizeof(ConnectionStatus));

	PipeList = std::auto_ptr<MY_USB_PIPE_INFO>(new MY_USB_PIPE_INFO[NumberOfOpenPipes]);
	MY_USB_PIPE_INFO *pPipeList = PipeList.get();
	for (i=0; i<NumberOfOpenPipes; ++i)
	{
		MY_USB_ENDPOINT_DESCRIPTOR *pED = (MY_USB_ENDPOINT_DESCRIPTOR *) &pPipeList[i].EndpointDescriptor;
		buffer.Read(&pED->bLength,          sizeof(pED->bLength));
		buffer.Read(&pED->bDescriptorType,  sizeof(pED->bDescriptorType));
		buffer.Read(&pED->bEndpointAddress, sizeof(pED->bEndpointAddress));
		buffer.Read(&pED->bmAttributes,     sizeof(pED->bmAttributes));
		buffer.Read(&pED->wMaxPacketSize,   sizeof(pED->wMaxPacketSize));
		buffer.Read(&pED->bInterval,        sizeof(pED->bInterval));

		buffer.Read(&pPipeList[i].ScheduleOffset, sizeof(pPipeList[i].ScheduleOffset));
	}
}

void MY_IOCTL_USB_GET_NODE_CONNECTION_NAME::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	buffer.Read(&ConnectionIndex, sizeof(ConnectionIndex));
	if (!isCompleted)
	{				
		return;
	}

	buffer.Read(&ActualLength, sizeof(ActualLength));

	NodeName = std::auto_ptr<wchar_t>(new wchar_t[ActualLength]);
	wchar_t *pNodeName = NodeName.get();
	for (i=0; i<ActualLength; ++i)
	{
		buffer.Read(&pNodeName[i],  sizeof(wchar_t));
	}
}

void MY_IOCTL_USB_GET_NODE_INFORMATION::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{				
		return;
	}

	buffer.Read(&NodeType, sizeof(NodeType));
	if (NodeType == UsbMIParent)
	{
		buffer.Read(&u.NumberOfInterfaces, sizeof(u.NumberOfInterfaces));
		return;
	}

	MY_USB_HUB_DESCRIPTOR *pHubDesc = &((MY_USB_HUB_INFORMATION *) &u)->HubDescriptor;

	buffer.Read(&pHubDesc->bDescriptorLength,   sizeof(pHubDesc->bDescriptorLength));
	buffer.Read(&pHubDesc->bDescriptorType,     sizeof(pHubDesc->bDescriptorType));
	buffer.Read(&pHubDesc->bNumberOfPorts,      sizeof(pHubDesc->bNumberOfPorts));
	buffer.Read(&pHubDesc->wHubCharacteristics, sizeof(pHubDesc->wHubCharacteristics));
	buffer.Read(&pHubDesc->bPowerOnToPowerGood, sizeof(pHubDesc->bPowerOnToPowerGood));
	buffer.Read(&pHubDesc->bHubControlCurrent,  sizeof(pHubDesc->bHubControlCurrent));
	buffer.Read(pHubDesc->bRemoveAndPowerMask,  sizeof(pHubDesc->bRemoveAndPowerMask));

    buffer.Read(&((MY_USB_HUB_INFORMATION *) &u)->HubIsBusPowered, sizeof(bool));
}